﻿using System;
using System.Collections.Generic;
using System.Text;
//
using Microsoft.Win32;


namespace RegistryLib
{
    // Registry.ClassesRoot 对应于 HKEY_CLASSES_ROOT 主键
    // Registry.CurrentUser 对应于 HKEY_CURRENT_USER 主键
    // Registry.LocalMachine 对应于 HKEY_LOCAL_MACHINE 主键
    // Registry.User 对应于 HKEY_USER 主键
    // Registry.CurrentConfig 对应于 HEKY_CURRENT_CONFIG 主键
    // Registry.DynDa 对应于 HKEY_DYN_DATA 主键
    // Registry.PerformanceData 对应于 HKEY_PERFORMANCE_DATA 主键
    /// <summary>
    /// 【HKEY_CURRENT_USER】注册表操作
    /// </summary>
    public class RegistryOperation
    {
        #region Const

        public const string REGISTRY_CURRENTUSER = "HKEY_CURRENT_USER"; // Windows 注册表基项 HKEY_CURRENT_USER
        public const string OPENSUBKEY = "Software"; // 打开的子项名称
        public const string CREATESUBKEY_WALL = "Wall"; // 创建的子项名称

        public const string SUBKEYNAME_SOFTKEYID = "SoftKeyID"; // 键值名称【加密锁编号】
        public const string SUBKEYNAME_MACHINENUM = "MachineNum"; // 键值名称【机器码】
        public const string SUBKEYNAME_TRIALTIMES = "TrialTimes"; // 键值名称【试用次数】
        public const string SUBKEYNAME_MENDTIME = "MendTime"; // 键值名称【补锁时间】
        public const string SUBKEYNAME_TOKEN = "Token"; // 键值名称【令牌】
        public const string SUBKEYNAME_RESETTIMES = "ResetTimes"; // 键值名称【重置次数】

        #endregion

        #region 公开的方法

        /// <summary>
        /// 打开注册表 openKey 子项
        /// </summary>
        /// <param name="openKey">打开子项</param>
        /// <returns></returns>
        public RegistryKey OpenSubKey(string openKey = null)
        {
            if (string.IsNullOrWhiteSpace(openKey))
                return Registry.CurrentUser.OpenSubKey(OPENSUBKEY, true);
            else
                return Registry.CurrentUser.OpenSubKey(openKey, true);
        }

        /// <summary>
        /// 创建注册表 subKey 子项
        /// </summary>
        /// <param name="openKey">打开子项</param>
        /// <param name="subKey">创建子项</param>
        /// <returns></returns>
        public RegistryKey CreateSubKey(string openKey = null, string subKey = null)
        {
            if (string.IsNullOrWhiteSpace(subKey))
                return OpenSubKey(openKey).CreateSubKey(CREATESUBKEY_WALL);
            else
                return OpenSubKey(openKey).CreateSubKey(subKey);
        }

        /// <summary>
        /// 根据键值名称获得键值
        /// </summary>
        /// <param name="openKey">打开子项</param>
        /// <param name="subKey">创建子项</param>
        /// <param name="subKeyName">键值名称</param>
        /// <returns>subKeyValue</returns>
        public object GetSubKeyValue(string openKey = null, string subKey = null, 
            string subKeyName = null)
        {
            if (string.IsNullOrWhiteSpace(subKeyName)) // 无键值名称时
                subKeyName = SUBKEYNAME_MACHINENUM;

            if (string.IsNullOrWhiteSpace(openKey))
                openKey = OPENSUBKEY; // 默认打开子项名称

            string[] subKeyNames; // 获取 subKey 子项所有子键的名称
            if (string.IsNullOrWhiteSpace(subKey))
            {
                subKeyNames = OpenSubKey(openKey).OpenSubKey(CREATESUBKEY_WALL, true).GetValueNames();
                subKey = CREATESUBKEY_WALL; // 默认创建子项名称
            }
            else
                subKeyNames = OpenSubKey(openKey).OpenSubKey(subKey, true).GetValueNames();

            if (subKeyNames != null && subKeyNames.Length > 0)
            {
                foreach (string keyName in subKeyNames)
                {
                    if (!string.IsNullOrWhiteSpace(keyName) &&
                        keyName.Equals(subKeyName))
                    {
                        // 获取该子键名称对应的键值
                        return Registry.GetValue(
                            string.Format(@"{0}\{1}\{2}", REGISTRY_CURRENTUSER, openKey, subKey), 
                            subKeyName, string.Empty); // HKEY_CURRENT_USER\Software\Wall
                    }
                }
            }

            return null;
        }

        /// <summary>
        /// 写键值对
        /// <para>如果指定的项不存在则创建该项</para>
        /// </summary>
        /// <param name="openKey">打开子项</param>
        /// <param name="subKey">创建子项</param>
        /// <param name="subKeyName">键值 key</param>
        /// <param name="subKeyValue">键值 value</param>
        /// <param name="valueKind">在存储数据时使用的注册表数据类型</param>
        public void SetSubKeyValue(string openKey = null, string subKey = null,
            string subKeyName = null, object subKeyValue = null, RegistryValueKind valueKind = RegistryValueKind.String)
        {
            if (string.IsNullOrWhiteSpace(subKeyName)) // 无键值名称时
                subKeyName = SUBKEYNAME_MACHINENUM;

            if (string.IsNullOrWhiteSpace(openKey))
                openKey = OPENSUBKEY; // 默认打开子项名称

            if (string.IsNullOrWhiteSpace(subKey))
                subKey = CREATESUBKEY_WALL; // 默认创建子项名称

            Registry.SetValue(string.Format(@"{0}\{1}\{2}", REGISTRY_CURRENTUSER, openKey, subKey),
                subKeyName, subKeyValue, valueKind); // 通过使用指定的注册表数据类型，设置该指定的注册表项的名称/值对。如果指定的项不存在，则创建该项。
        }

        #endregion
    }
}
